<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>PyMOTW: asyncore &mdash; PyMOTW Document v1.6 documentation</title>
    <link rel="stylesheet" href="../_static/mytest.css" type="text/css" />
    <link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '../',
        VERSION:     '1.6',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="../_static/jquery.js"></script>
    <script type="text/javascript" src="../_static/doctools.js"></script>
    
    <!-- comment utility -->
    <link rel="stylesheet" href="../_static/comment.css" type="text/css" />
    <script type="text/javascript" src="../_static/md5.js"></script>
    <script type="text/javascript" src="../_static/comment.js"></script>
    <!-- end -->
    <link rel="author" title="About these documents" href="../about.html" />
    <link rel="copyright" title="Copyright" href="../copyright.html" />
    <link rel="top" title="PyMOTW Document v1.6 documentation" href="../index.html" />
    <link rel="next" title="PyMOTW: tempfile" href="tempfile.html" />
    <link rel="prev" title="PyMOTW: SocketServer" href="SocketServer.html" /> 
  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="tempfile.html" title="PyMOTW: tempfile"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="SocketServer.html" title="PyMOTW: SocketServer"
             accesskey="P">previous</a> |</li>
        <li><a href="../index.html">PyMOTW Document v1.6 documentation</a> &raquo;</li> 
      </ul>
    </div> 
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper">
            <h3><a href="../index.html">Table Of Contents</a></h3>
            <ul>
<li><a class="reference external" href="">PyMOTW: asyncore</a><ul>
<li><a class="reference external" href="#id1">客户端</a></li>
<li><a class="reference external" href="#id2">服务器</a></li>
<li><a class="reference external" href="#id3">其他循环事件的处理</a></li>
<li><a class="reference external" href="#id4">文件处理</a></li>
<li><a class="reference external" href="#id5">参考</a></li>
</ul>
</li>
</ul>

            <h4>Previous topic</h4>
            <p class="topless"><a href="SocketServer.html"
                                  title="previous chapter">PyMOTW: SocketServer</a></p>
            <h4>Next topic</h4>
            <p class="topless"><a href="tempfile.html"
                                  title="next chapter">PyMOTW: tempfile</a></p>
            <h3>This Page</h3>
            <ul class="this-page-menu">
              <li><a href="../_sources/documents/asyncore.txt"
                     rel="nofollow">Show Source</a></li>
            </ul>
          <div id="searchbox" style="display: none">
            <h3>Quick search</h3>
              <form class="search" action="../search.html" method="get">
                <input type="text" name="q" size="18" />
                <input type="submit" value="Go" />
                <input type="hidden" name="check_keywords" value="yes" />
                <input type="hidden" name="area" value="default" />
              </form>
              <p class="searchtip" style="font-size: 90%">
              Enter search terms or a module, class or function name.
              </p>
          </div>
          <script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div> 

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="pymotw-asyncore">
<h1>PyMOTW: asyncore<a class="headerlink" href="#pymotw-asyncore" title="Permalink to this headline">¶</a></h1>
<ul class="simple">
<li>模块： asyncore</li>
<li>目的： 异步I/O操作</li>
<li>python版本： 1.5.2+</li>
</ul>
<p>asyncore模块包含了使用I/O对象如sockets以方便我们异步的进行操作(可以代替例如线程). 他提供的主要类是dispatcher, 是一个封装了一个socket并提供了处理如连接, 读取, 写入等的事件钩子, 这些会在主循环函数loop()中被调用.</p>
<div class="section" id="id1">
<h2>客户端<a class="headerlink" href="#id1" title="Permalink to this headline">¶</a></h2>
<p>创建一个异步客户端，继承dispatcher并提供了创建, 读取和写入socket的实现. 让我们拿HTTP客户端来做示例, 它基于一个来自标准库文档的例子.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">asyncore</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">from</span> <span class="nn">cStringIO</span> <span class="kn">import</span> <span class="n">StringIO</span>
<span class="kn">import</span> <span class="nn">urlparse</span>

<span class="k">class</span> <span class="nc">HttpClient</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">url</span> <span class="o">=</span> <span class="n">url</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">url</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">parsed_url</span> <span class="o">=</span> <span class="n">urlparse</span><span class="o">.</span><span class="n">urlparse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
        <span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">write_buffer</span> <span class="o">=</span> <span class="s">&#39;GET </span><span class="si">%s</span><span class="s"> HTTP/1.0</span><span class="se">\r\n\r\n</span><span class="s">&#39;</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">url</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">read_buffer</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
        <span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parsed_url</span><span class="o">.</span><span class="n">netloc</span><span class="p">,</span> <span class="mf">80</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;connecting to </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="n">address</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">connect</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle_connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_connect()&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_close()&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">writable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">is_writable</span> <span class="o">=</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">write_buffer</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mf">0</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">is_writable</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;writable() -&gt; </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="n">is_writable</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">is_writable</span>

    <span class="k">def</span> <span class="nf">readable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;readable() -&gt; True&#39;</span><span class="p">)</span>
        <span class="k">return</span> <span class="bp">True</span>

    <span class="k">def</span> <span class="nf">handle_write</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">write_buffer</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_write() -&gt; &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">write_buffer</span><span class="p">[:</span><span class="n">sent</span><span class="p">])</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">write_buffer</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">write_buffer</span><span class="p">[</span><span class="n">sent</span><span class="p">:]</span>

    <span class="k">def</span> <span class="nf">handle_read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">8192</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_read() -&gt; </span><span class="si">%d</span><span class="s"> bytes&#39;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">read_buffer</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>


<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">,</span>
      <span class="n">format</span><span class="o">=</span><span class="s">&#39;</span><span class="si">%(name)s</span><span class="s">: </span><span class="si">%(message)s</span><span class="s">&#39;</span><span class="p">,</span>
    <span class="p">)</span>

    <span class="n">clients</span> <span class="o">=</span> <span class="p">[</span>
      <span class="n">HttpClient</span><span class="p">(</span><span class="s">&#39;http://www.python.org/&#39;</span><span class="p">),</span>
      <span class="n">HttpClient</span><span class="p">(</span><span class="s">&#39;http://www.doughellmann.com/PyMOTW/contents.html&#39;</span><span class="p">),</span>
    <span class="p">]</span>

    <span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;LOOP STARTING&#39;</span><span class="p">)</span>
    <span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;LOOP DONE&#39;</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">clients</span><span class="p">:</span>
        <span class="n">response_body</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="n">read_buffer</span><span class="o">.</span><span class="n">getvalue</span><span class="p">()</span>
        <span class="k">print</span> <span class="n">c</span><span class="o">.</span><span class="n">url</span><span class="p">,</span> <span class="s">&#39;got&#39;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">response_body</span><span class="p">),</span> <span class="s">&#39;bytes&#39;</span>
</pre></div>
</div>
<p>首先，通过在 <tt class="docutils literal"><span class="pre">__init__()</span></tt> 中使用基类的 <tt class="docutils literal"><span class="pre">create_socket()</span></tt> 方法创建socket. 当然还有其他的方法, 但在这个例子中. 我们创建的是一个TCP/IP socket. 因此使用基类已经可以满足需要了.</p>
<p>handle_connect()钩子简单的显示了被调用的信息. 其他客户端还可以在 <tt class="docutils literal"><span class="pre">handle_connect()</span></tt> 中进行一些握手或者协议交涉等类似的处理.</p>
<p>handle_close()同样的显示了被调用的信息. 基类可以正确的关闭socket, 如果你不想作额外的工作可以交给函数来处理.</p>
<p>asyncore循环中, 使用 <tt class="docutils literal"><span class="pre">writeable()</span></tt> 和同属方法 <tt class="docutils literal"><span class="pre">readable()</span></tt> 决定什么样的操作来处理每个dispatcher. 实际上, sockets的 <tt class="docutils literal"><span class="pre">poll()</span></tt> 和 <tt class="docutils literal"><span class="pre">select()</span></tt> 方法或由每个dispatcher操作的文件描述符会在asyncore代码内部处理. 因此你不必自己来实现这些. 只需简单的指出某dispatcher是否是对读和写都要处理. 在这个HTTP client的例子中, 只要存在请求发送到服务器的数据, <tt class="docutils literal"><span class="pre">writable()</span></tt> 会返回True, 而 <tt class="docutils literal"><span class="pre">readable()</span></tt> 一直返回True, 因为我们想读取所有到来的数据.</p>
<p>在每次循环中, 当 <tt class="docutils literal"><span class="pre">writable()</span></tt> 正确响应, <tt class="docutils literal"><span class="pre">handle_write()</span></tt> 会被调用. 在这个例子中, 在 <tt class="docutils literal"><span class="pre">__init__()</span></tt> 中创建的HTTP请求字符串会被发送到服务器, 写缓冲区会清除成功发送的数据.</p>
<p>类似地, 当 <tt class="docutils literal"><span class="pre">readable()</span></tt> 正确响应, 也就是有数据要读取了. 那么, <tt class="docutils literal"><span class="pre">handle_read()</span></tt> 会被调用.</p>
<p>例子中__main__之后的代码首先配置一个日志记录以便调试, 然后创建了两个客户端分别下载网页. 创建客户端需要在一个由asyncore内部保存的 <em>map</em> 中注册. 随着主循环的开始, 客户端的下载也开始, 当一个客户端从可读socket中读取0个字节, 这会被解释成关闭连接然后.</p>
<p>下面是这个例子中客户端app运行出的可能结果:</p>
<div class="highlight-python"><pre>$ python asyncore_http_client.py
http://www.python.org/: connecting to ('www.python.org', 80)
http://www.doughellmann.com/PyMOTW/contents.html: connecting to ('www.doughellmann.com', 80)
root: LOOP STARTING
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_connect()
http://www.doughellmann.com/PyMOTW/contents.html: handle_write() -&gt; "GET http://www.doughellmann.com/PyMOTW/contents.html HTTP/1.0

"
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 3163 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 2896 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 2896 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 2896 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 2896 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 895 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_close()
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 0 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.python.org/: handle_connect()
http://www.python.org/: handle_write() -&gt; "GET http://www.python.org/ HTTP/1.0

"
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1257 bytes
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_close()
http://www.python.org/: handle_read() -&gt; 0 bytes
root: LOOP DONE
http://www.python.org/ got 18009 bytes
http://www.doughellmann.com/PyMOTW/contents.html got 22882 bytes</pre>
</div>
</div>
<div class="section" id="id2">
<h2>服务器<a class="headerlink" href="#id2" title="Permalink to this headline">¶</a></h2>
<p>下面的例子, 通过重新实现SocketServe中的EchoServer例子来说明如何在服务器上使用异步. 这里主要有3个类: EchoServer用于接收来自客户端的连接并创建各自的EchoHandler实例, EchoClient是类似于HTTPClient的异步dispatche.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">asyncore</span>
<span class="kn">import</span> <span class="nn">logging</span>

<span class="k">class</span> <span class="nc">EchoServer</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Receives connections and establishes handlers for each client.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">address</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">&#39;EchoServer&#39;</span><span class="p">)</span>
        <span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">bind</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">address</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">socket</span><span class="o">.</span><span class="n">getsockname</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;binding to </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">address</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="k">def</span> <span class="nf">handle_accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c"># Called when a client connects to our socket</span>
        <span class="n">client_info</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">accept</span><span class="p">()</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_accept() -&gt; </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="n">client_info</span><span class="p">[</span><span class="mf">1</span><span class="p">])</span>
        <span class="n">EchoHandler</span><span class="p">(</span><span class="n">sock</span><span class="o">=</span><span class="n">client_info</span><span class="p">[</span><span class="mf">0</span><span class="p">])</span>
        <span class="c"># We only want to deal with one client at a time,</span>
        <span class="c"># so close as soon as we set up the handler.</span>
        <span class="c"># Normally you would not do this and the server</span>
        <span class="c"># would run forever or until it received instructions</span>
        <span class="c"># to stop.</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">handle_close</span><span class="p">()</span>
        <span class="k">return</span>

    <span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_close()&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
        <span class="k">return</span>

<span class="k">class</span> <span class="nc">EchoHandler</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Handles echoing messages from a single client.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="p">,</span> <span class="n">chunk_size</span><span class="o">=</span><span class="mf">256</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">chunk_size</span> <span class="o">=</span> <span class="n">chunk_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">&#39;EchoHandler</span><span class="si">%s</span><span class="s">&#39;</span> <span class="o">%</span> <span class="nb">str</span><span class="p">(</span><span class="n">sock</span><span class="o">.</span><span class="n">getsockname</span><span class="p">()))</span>
        <span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="o">=</span><span class="n">sock</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data_to_write</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="k">return</span>

    <span class="k">def</span> <span class="nf">writable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;We want to write if we have received data.&quot;&quot;&quot;</span>
        <span class="n">response</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data_to_write</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;writable() -&gt; </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="n">response</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">response</span>


    <span class="k">def</span> <span class="nf">handle_write</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Write as much as possible of the most recent message we have received.&quot;&quot;&quot;</span>
        <span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">data_to_write</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">data</span><span class="p">[:</span><span class="bp">self</span><span class="o">.</span><span class="n">chunk_size</span><span class="p">])</span>
        <span class="k">if</span> <span class="n">sent</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
            <span class="n">remaining</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="n">sent</span><span class="p">:]</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">data_to_write</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">remaining</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_write() -&gt; (</span><span class="si">%d</span><span class="s">) &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="n">sent</span><span class="p">,</span> <span class="n">data</span><span class="p">[:</span><span class="n">sent</span><span class="p">])</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">writable</span><span class="p">():</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">handle_close</span><span class="p">()</span>

    <span class="k">def</span> <span class="nf">handle_read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="sd">&quot;&quot;&quot;Read an incoming message from the client and put it into our outgoing queue.&quot;&quot;&quot;</span>
        <span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">chunk_size</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_read() -&gt; (</span><span class="si">%d</span><span class="s">) &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">data</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">data_to_write</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span> <span class="n">data</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_close()&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>



<span class="k">class</span> <span class="nc">EchoClient</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Sends messages to the server and receives responses.</span>
<span class="sd">    &quot;&quot;&quot;</span>

    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">chunk_size</span><span class="o">=</span><span class="mf">512</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">message</span> <span class="o">=</span> <span class="n">message</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">to_send</span> <span class="o">=</span> <span class="n">message</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">received_data</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">chunk_size</span> <span class="o">=</span> <span class="n">chunk_size</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s">&#39;EchoClient&#39;</span><span class="p">)</span>
        <span class="n">asyncore</span><span class="o">.</span><span class="n">dispatcher</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="o">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="o">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;connecting to </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">connect</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
        <span class="k">return</span>

    <span class="k">def</span> <span class="nf">handle_connect</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_connect()&#39;</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_close()&#39;</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
        <span class="n">received_message</span> <span class="o">=</span> <span class="s">&#39;&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">received_data</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">received_message</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">message</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;RECEIVED COPY OF MESSAGE&#39;</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;ERROR IN TRANSMISSION&#39;</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;EXPECTED &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">message</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;RECEIVED &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="n">received_message</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="k">def</span> <span class="nf">writable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;writable() -&gt; </span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">to_send</span><span class="p">))</span>
        <span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">to_send</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle_write</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">sent</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">to_send</span><span class="p">[:</span><span class="bp">self</span><span class="o">.</span><span class="n">chunk_size</span><span class="p">])</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_write() -&gt; (</span><span class="si">%d</span><span class="s">) &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="n">sent</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">to_send</span><span class="p">[:</span><span class="n">sent</span><span class="p">])</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">to_send</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">to_send</span><span class="p">[</span><span class="n">sent</span><span class="p">:]</span>

    <span class="k">def</span> <span class="nf">handle_read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">chunk_size</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;handle_read() -&gt; (</span><span class="si">%d</span><span class="s">) &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">data</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">received_data</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="kn">import</span> <span class="nn">socket</span>
    <span class="kn">import</span> <span class="nn">threading</span>

    <span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">,</span>
      <span class="n">format</span><span class="o">=</span><span class="s">&#39;</span><span class="si">%(name)s</span><span class="s">: </span><span class="si">%(message)s</span><span class="s">&#39;</span><span class="p">,</span>
    <span class="p">)</span>

    <span class="n">address</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;localhost&#39;</span><span class="p">,</span> <span class="mf">0</span><span class="p">)</span> <span class="c"># let the kernel give us a port</span>
    <span class="n">server</span> <span class="o">=</span> <span class="n">EchoServer</span><span class="p">(</span><span class="n">address</span><span class="p">)</span>
    <span class="n">ip</span><span class="p">,</span> <span class="n">port</span> <span class="o">=</span> <span class="n">server</span><span class="o">.</span><span class="n">address</span> <span class="c"># find out what port we were given</span>
    <span class="n">client</span> <span class="o">=</span> <span class="n">EchoClient</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">message</span><span class="o">=</span><span class="nb">open</span><span class="p">(</span><span class="s">&#39;lorem.txt&#39;</span><span class="p">,</span> <span class="s">&#39;r&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
    <span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span>
</pre></div>
</div>
<p>EchoServer和EchoHandler被定义在独立的类中因为他们各自处理不同的事情. 当EchoServer接收一个连接, 一个新的socket被建立. 一个利用socket map(这是由asyncore内部维护的)的EchoHandler被创建, 而不是在EchoServer内部进行各个客户端请求的分配.</p>
<div class="highlight-python"><pre>$ python asyncore_echo_server.py
EchoServer: binding to ('127.0.0.1', 52235)
EchoClient: connecting to ('127.0.0.1', 52235)
EchoClient: writable() -&gt; True
EchoServer: handle_accept() -&gt; ('127.0.0.1', 52236)
EchoServer: handle_close()
EchoClient: handle_connect()
EchoClient: handle_write() -&gt; (512) "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a
elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla
facilisi. Sed tristique eros eu libero. Pellentesque vel arcu. Vivamus
purus orci, iaculis ac, suscipit sit amet, pulvinar eu,
lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas
dui. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Aliquam viverra f"
EchoClient: writable() -&gt; True
EchoHandler('127.0.0.1', 52235): writable() -&gt; False
EchoHandler('127.0.0.1', 52235): handle_read() -&gt; (256) "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a
elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla
facilisi. Sed tristique eros eu libero. Pellentesque ve"
EchoClient: handle_write() -&gt; (225) "ringilla
leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed
mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut
eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet
justo.
"
EchoClient: writable() -&gt; False
EchoHandler('127.0.0.1', 52235): writable() -&gt; True
EchoHandler('127.0.0.1', 52235): handle_read() -&gt; (256) "l arcu. Vivamus
purus orci, iaculis ac, suscipit sit amet, pulvinar eu,
lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas
dui. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Aliquam viverra f"
EchoHandler('127.0.0.1', 52235): handle_write() -&gt; (256) "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a
elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla
facilisi. Sed tristique eros eu libero. Pellentesque ve"
EchoHandler('127.0.0.1', 52235): writable() -&gt; True
EchoClient: writable() -&gt; False
EchoHandler('127.0.0.1', 52235): writable() -&gt; True
EchoClient: handle_read() -&gt; (256) "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a
elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla
facilisi. Sed tristique eros eu libero. Pellentesque ve"
EchoHandler('127.0.0.1', 52235): handle_read() -&gt; (225) "ringilla
leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed
mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut
eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet
justo.
"
EchoHandler('127.0.0.1', 52235): handle_write() -&gt; (256) "l arcu. Vivamus
purus orci, iaculis ac, suscipit sit amet, pulvinar eu,
lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas
dui. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Aliquam viverra f"
EchoHandler('127.0.0.1', 52235): writable() -&gt; True
EchoClient: writable() -&gt; False
EchoHandler('127.0.0.1', 52235): writable() -&gt; True
EchoClient: handle_read() -&gt; (256) "l arcu. Vivamus
purus orci, iaculis ac, suscipit sit amet, pulvinar eu,
lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas
dui. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Aliquam viverra f"
EchoHandler('127.0.0.1', 52235): handle_write() -&gt; (225) "ringilla
leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed
mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut
eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet
justo.
"
EchoHandler('127.0.0.1', 52235): writable() -&gt; False
EchoHandler('127.0.0.1', 52235): handle_close()
EchoClient: writable() -&gt; False
EchoClient: handle_read() -&gt; (225) "ringilla
leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed
mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut
eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet
justo.
"
EchoClient: writable() -&gt; False
EchoClient: handle_close()
EchoClient: RECEIVED COPY OF MESSAGE
EchoClient: handle_read() -&gt; (0) ""</pre>
</div>
<p>在这个例子中, 服务器, 处理者, 客户端对象都被asyncore在一个单独进程中使用一相同的socket map维护. 将服务器和客户端分开, 简单的将相关代码分开, 并且在各自程序中运行 <tt class="docutils literal"><span class="pre">asyncore.loop()</span></tt>. 当一个dispatcher被关闭了, 会从map中删掉, 整个循环会在map为空时停下来.</p>
</div>
<div class="section" id="id3">
<h2>其他循环事件的处理<a class="headerlink" href="#id3" title="Permalink to this headline">¶</a></h2>
<p>有时候需必须在已有的应用事件中加入异步事件. 例如, 一个GUI应用不想在所有异步操作处理时阻断UI-这是违背了异步的目的. 为了使这种集成更方便, <tt class="docutils literal"><span class="pre">asycore.loop()</span></tt> 接收一个用于设置超时的参数和一个用于限制循环次数的参数, 重新使用第一个例子中的HttpClient, 我们可以看到他们各自的效果.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">asyncore</span>
<span class="kn">import</span> <span class="nn">logging</span>

<span class="kn">from</span> <span class="nn">asyncore_http_client</span> <span class="kn">import</span> <span class="n">HttpClient</span>

<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">,</span>
  <span class="n">format</span><span class="o">=</span><span class="s">&#39;</span><span class="si">%(name)s</span><span class="s">: </span><span class="si">%(message)s</span><span class="s">&#39;</span><span class="p">,</span>
<span class="p">)</span>

<span class="n">clients</span> <span class="o">=</span> <span class="p">[</span>
  <span class="n">HttpClient</span><span class="p">(</span><span class="s">&#39;http://www.doughellmann.com/PyMOTW/contents.html&#39;</span><span class="p">),</span>
  <span class="n">HttpClient</span><span class="p">(</span><span class="s">&#39;http://www.python.org/&#39;</span><span class="p">),</span>
<span class="p">]</span>

<span class="n">loop_counter</span> <span class="o">=</span> <span class="mf">0</span>
<span class="k">while</span> <span class="n">asyncore</span><span class="o">.</span><span class="n">socket_map</span><span class="p">:</span>
    <span class="n">loop_counter</span> <span class="o">+=</span> <span class="mf">1</span>
    <span class="n">logging</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;loop_counter=</span><span class="si">%s</span><span class="s">&#39;</span><span class="p">,</span> <span class="n">loop_counter</span><span class="p">)</span>
    <span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="mf">1</span><span class="p">,</span> <span class="n">count</span><span class="o">=</span><span class="mf">1</span><span class="p">)</span>
</pre></div>
</div>
<p>我们可以看到, 在 <tt class="docutils literal"><span class="pre">asyncore.loop()</span></tt> 中调用时, 客户端仅读或写数据一次, 替代我们自己的while循环. 我们可以在GUI工具包活其他需要这种功能机制的地方类似的调用 <tt class="docutils literal"><span class="pre">asyncore.loop()</span></tt> (ui不会忙于处理其他事件).</p>
<div class="highlight-python"><pre>$ python asyncore_loop.py

http://www.doughellmann.com/PyMOTW/contents.html: connecting to ('www.doughellmann.com', 80)
http://www.python.org/: connecting to ('www.python.org', 80)
root: loop_counter=1
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: writable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_connect()
http://www.doughellmann.com/PyMOTW/contents.html: handle_write() -&gt; "GET http://www.doughellmann.com/PyMOTW/contents.html HTTP/1.0

"
root: loop_counter=2
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 267 bytes
root: loop_counter=3
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 8192 bytes
root: loop_counter=4
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 6288 bytes
root: loop_counter=5
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
root: loop_counter=6
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 1448 bytes
root: loop_counter=7
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 2896 bytes
root: loop_counter=8
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 2343 bytes
root: loop_counter=9
http://www.doughellmann.com/PyMOTW/contents.html: readable() -&gt; True
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.doughellmann.com/PyMOTW/contents.html: handle_close()
http://www.doughellmann.com/PyMOTW/contents.html: handle_read() -&gt; 0 bytes
root: loop_counter=10
http://www.python.org/: readable() -&gt; True
http://www.python.org/: writable() -&gt; True
http://www.python.org/: handle_connect()
http://www.python.org/: handle_write() -&gt; "GET http://www.python.org/ HTTP/1.0

"
root: loop_counter=11
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=12
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=13
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=14
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=15
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=16
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=17
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=18
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=19
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=20
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=21
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=22
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1396 bytes
root: loop_counter=23
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_read() -&gt; 1257 bytes
root: loop_counter=24
http://www.python.org/: readable() -&gt; True
http://www.python.org/: handle_close()
http://www.python.org/: handle_read() -&gt; 0 bytes</pre>
</div>
</div>
<div class="section" id="id4">
<h2>文件处理<a class="headerlink" href="#id4" title="Permalink to this headline">¶</a></h2>
<p>一般情况下, 你可能只想在sockets中使用asyncore, 但有时异步的读取文件也是有用的(当测试网络服务器而不需要网络设置使用文件，或者是部分读取, 写入大数据文件）在这些情况下, asyncore提供了file_dispatcher和file_wrapper类.</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">asyncore</span>
<span class="kn">import</span> <span class="nn">os</span>

<span class="k">class</span> <span class="nc">FileReader</span><span class="p">(</span><span class="n">asyncore</span><span class="o">.</span><span class="n">file_dispatcher</span><span class="p">):</span>

    <span class="k">def</span> <span class="nf">writable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">False</span>

    <span class="k">def</span> <span class="nf">handle_read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">recv</span><span class="p">(</span><span class="mf">256</span><span class="p">)</span>
        <span class="k">print</span> <span class="s">&#39;READ: (</span><span class="si">%d</span><span class="s">) &quot;</span><span class="si">%s</span><span class="s">&quot;&#39;</span> <span class="o">%</span> <span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">),</span> <span class="n">data</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">handle_expt</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c"># Ignore events that look like out of band data</span>
        <span class="k">pass</span>

    <span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>

<span class="n">lorem_fd</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="s">&#39;lorem.txt&#39;</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">O_RDONLY</span><span class="p">)</span>
<span class="n">reader</span> <span class="o">=</span> <span class="n">FileReader</span><span class="p">(</span><span class="n">lorem_fd</span><span class="p">)</span>
<span class="n">asyncore</span><span class="o">.</span><span class="n">loop</span><span class="p">()</span>
</pre></div>
</div>
<p>这个例子在Python2.5.2下进行测试, 我使用了 <tt class="docutils literal"><span class="pre">os.open()</span></tt> 获得文件描述符. 对于Python2.6之后, file_dispatcher自动将所有具有 <tt class="docutils literal"><span class="pre">fileno()</span></tt> 方法的东西转换成一个文件描述符.</p>
<div class="highlight-python"><pre>$ python asyncore_file_dispatcher.py
READ: (256) "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec
egestas, enim et consectetuer ullamcorper, lectus ligula rutrum leo, a
elementum elit tortor eu quam. Duis tincidunt nisi ut ante. Nulla
facilisi. Sed tristique eros eu libero. Pellentesque ve"
READ: (256) "l arcu. Vivamus
purus orci, iaculis ac, suscipit sit amet, pulvinar eu,
lacus. Praesent placerat tortor sed nisl. Nunc blandit diam egestas
dui. Pellentesque habitant morbi tristique senectus et netus et
malesuada fames ac turpis egestas. Aliquam viverra f"
READ: (225) "ringilla
leo. Nulla feugiat augue eleifend nulla. Vivamus mauris. Vivamus sed
mauris in nibh placerat egestas. Suspendisse potenti. Mauris massa. Ut
eget velit auctor tortor blandit sollicitudin. Suspendisse imperdiet
justo.
"
READ: (0) ""</pre>
</div>
</div>
<div class="section" id="id5">
<h2>参考<a class="headerlink" href="#id5" title="Permalink to this headline">¶</a></h2>
<ul class="simple">
<li><a class="reference external" href="http://docs.python.org/library/asyncore.html">asyncore: 该模块的标准库文档</a></li>
</ul>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="../genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="tempfile.html" title="PyMOTW: tempfile"
             >next</a> |</li>
        <li class="right" >
          <a href="SocketServer.html" title="PyMOTW: SocketServer"
             >previous</a> |</li>
        <li><a href="../index.html">PyMOTW Document v1.6 documentation</a> &raquo;</li> 
      </ul>
    </div>
    <div class="footer">
      &copy; <a href="../copyright.html">Copyright</a> 2009, vbarter &amp; liz.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 0.6.3.
    </div>
  </body>
</html>